// For secuences of images in a folder

#include "aux_functions_def.hpp"
#include "aux_functions_impl.hpp"


inline	
grassmann_points::grassmann_points( std::string  in_video_path,  field<std::string> in_frame_list, double in_vec_size, int in_p)
:frame_list(in_frame_list), video_path(in_video_path), vec_size(in_vec_size), p(in_p)
{
  creating_GrassField();
  //borrar_function();
  
}

inline
void
grassmann_points::creating_GrassField()
{
  double nf = frame_list.n_rows;
  double ni = 10; // # of consecutive images to be used to calculate the point in the manifold
  
  //dist_frames.zeros(nf - 1); //Distance between consecutive frames to calculate the number of clusters
  acc = 0;
  cout << "# images to calculate a point on the manifold is " << ni << endl;
  cout << "# of frames " << nf << endl;
  double n_points = floor(nf/ni); // 
  cout << "n_points " << n_points << endl;
  //n_points + 1 in the last position is the number of clusters
  GrassField.set_size(n_points,1); // Field with all Grassmann Points
  uword pos = 0;
  //10 because this 
  
   for (uword f = 0; f <  n_points*ni; f+=ni)//  Should be nf, but iI want this to be multiple of ni (10).
    {
      //cout << "f= " << f << endl;
      field<std::string>  name_frames(ni,1);
      
      for (uword i = 0; i < ni; ++i)
      {
	name_frames(i,0) = frame_list(f+i);
      }
      
      //name_frames.print("name_frames");
      //getchar();
      GrassField(pos,0) = creating_GrassPoint(name_frames);
      pos++;
    }
    //QUITAR ESTO y todo lo que se le relaciona :)
    //dist_frames.t().print("dist_frames");
    //int K = 0;
    //set_Kclusters();
    //cout << "Number of clusters set to: " << K << endl;
    //GrassField(pos,0) = K; // In the last position I'm saving the number of clusters
  //getchar();
}


inline
mat
grassmann_points::creating_GrassPoint(field<std::string>  name_frames)
{
  uword n_frames = name_frames.n_rows;
  mat F = zeros(vec_size,n_frames); //vec_size is an input
  
  
  
  //cout << "# of frames " << n_frames << endl;
  for (uword n = 0; n < n_frames;  ++n)
  {
    std::stringstream tmp_name;
    tmp_name << video_path << name_frames(n,0); ///ojo
    //cout << tmp_name.str() << endl;
    cv::Mat cvImage;
    cvImage = cv::imread(tmp_name.str(), CV_LOAD_IMAGE_GRAYSCALE);
    
    //Showing Actions:
     //cv::namedWindow("Image", CV_WINDOW_AUTOSIZE );
     //cv::imshow("Image", cvImage);
     //cv::waitKey(50);
     //cout << cvImage.cols << " & "<<cvImage.rows << endl;
    
    aux_functions aux_fx;
    mat frame;
    frame = aux_fx.convert2Arma(cvImage); 
    //frame = aux_fx.convert2Arma(cvImage,5); ///ojo

    mat tmp_frame;
    tmp_frame = reshape(frame,vec_size,1); 
    vec v = conv_to<vec>::from(tmp_frame);
    F.col(n) = v; // Image set
    
    /*Esto lo usaba para calcular el # de clusters
    if (n == 0 && acc == 0 )
    {
      
      //cout << "Primer caso n: " << n << " - acc: " << acc << endl;
      tmp_vec = v;
    }
    else
    {
      //cout << "n: " << n << "acc: " << acc << endl;
      dist_frames(acc) = norm (F.col(n) - tmp_vec, 2); 
      acc++;
    }
    tmp_vec = v;
    */
  }
  
  //Orthogonalization Procedure using SVD
  //Check it =).
  mat U; vec s;   mat V;
  svd(U,s,V,F); 

  //cout << "U.n_cols: "<< U.n_cols << endl;
  mat Gnp = U.cols(0,p-1);
  //Gnp.print("Gnp");
  //cout << "F.   "  << "rows= "  << F.n_rows   <<  ". cols= "  << F.n_cols   << endl;
  //cout << "U.   "  << "rows= "  << U.n_rows   <<  ". cols= "  << U.n_cols   << endl;
  //cout << "s.   "  << "rows= "  << s.n_rows   <<  ". cols= "  << s.n_cols   << endl;
  //cout << "Gnp. "  << "rows= "  << Gnp.n_rows <<  ". cols= "  << Gnp.n_cols << endl;
  //getchar();
  return Gnp;
}


inline
field<mat> 
grassmann_points::get_GrassPoints()
{
 return  GrassField;
}

inline	
void
grassmann_points::save_GrassPoints(std::string name)
{
 GrassField.save(name);

}



inline
void
grassmann_points::borrar_function()
{
  double n_frames = frame_list.n_rows;
  vec dist_frames_borr;
  dist_frames_borr.zeros(n_frames-1);
  int acc2 = 0;
  mat F2 = zeros(vec_size,n_frames);;
  for (uword n = 0; n < n_frames;  ++n)
  {
    std::stringstream tmp_name;
    tmp_name << video_path << frame_list(n,0); ///ojo
    //cout << tmp_name.str() << endl;
    cv::Mat cvImage;
    cvImage = cv::imread(tmp_name.str(), CV_LOAD_IMAGE_GRAYSCALE);
    
    //Showing Actions:
     //cv::namedWindow("Image", CV_WINDOW_AUTOSIZE );
     //cv::imshow("Image", cvImage);
     //cv::waitKey(50);
     //cout << cvImage.cols << " & "<<cvImage.rows << endl;
    
    aux_functions aux_fx;
    mat frame;
    //frame = aux_fx.convert2Arma(cvImage); 
    frame = aux_fx.convert2Arma(cvImage,5); ///ojo

    mat tmp_frame;
    tmp_frame = reshape(frame,vec_size,1); 
    vec v = conv_to<vec>::from(tmp_frame);
    F2.col(n) = v; // Image set
    
    if (n>0)
    {
      //cout << "n: " << n << "acc: " << acc << endl;
      dist_frames_borr(acc2) = norm (F2.col(n) - F2.col(n-1), 2); 
      acc2++;
    }
  }
    
    dist_frames_borr.print("dist_frames_borr");
    
}

inline
int
grassmann_points::set_Kclusters()
{
  //int K =0;
  double mu    = mean(dist_frames);
  double st_dev  = stddev(dist_frames);
  
  cout << "mu: " << mu << endl;
  cout << "st_dev: " << st_dev << endl;
  uvec q1 = find (dist_frames> mu + st_dev);
  return q1.n_elem;

}